package cn.kgc.vue.service.impl;

import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.MD5;
import cn.kgc.vue.commons.Const;
import cn.kgc.vue.commons.QueryCondition;
import cn.kgc.vue.commons.ResponseResult;
import cn.kgc.vue.entity.*;
import cn.kgc.vue.form.UserForm;
import cn.kgc.vue.mapper.*;
import cn.kgc.vue.utils.IpUtil;
import cn.kgc.vue.utils.JWTUtil;
import cn.kgc.vue.vo.UserVo;
import com.baomidou.mybatisplus.annotation.Version;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.kgc.vue.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.http.HttpRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* @author 11839
* @description 针对表【sys_user】的数据库操作Service实现
* @createDate 2024-06-28 15:23:44
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private JWTUtil jwtUtil;
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RolePersMapper rolePersMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public ResponseResult getCaptcha() {
        //创建验证码对象
        LineCaptcha lineCaptcha = new LineCaptcha(110, 40,4,4);
        String code=lineCaptcha.getCode();
        String uuid = IdUtil.simpleUUID();
        //图片转换为json格式
        String image = lineCaptcha.getImageBase64();
         stringRedisTemplate.opsForValue().set(uuid,code,3, TimeUnit.MINUTES);
        

        return ResponseResult.success().data("uuid", uuid).data("code", code).data("image", image);
    }

    @Override
    public ResponseResult login(HashMap<String, Object> params, HttpServletRequest request) {
        //验证码校验
        String uuid = (String)params.get("uuid");

        String redisCode = stringRedisTemplate.opsForValue().get(uuid);
         if (StringUtils.isBlank(redisCode)) {
             return ResponseResult.fail().message("验证码失效,请刷新重试!!!");
         }

         //验证码是否正确
        String code = (String)params.get("code");
          if (!StringUtils.equals(code,redisCode)){
              return ResponseResult.fail().message("验证码错误");
          }


        //根据用户名查询信息
        String username = (String)params.get("username");
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getUsername, username);
        User user = baseMapper.selectOne(lambda);
        if (ObjectUtils.isNull(user)){
            return ResponseResult.fail().message("用户名错误");
        }
        //比较密码
        String formPassword=(String)params.get("password");
        String salt = user.getSalt();
        String hex = new Md5Hash(formPassword, salt, 10).toHex();

        String DbPassWord = user.getPassword();
        if (!StringUtils.equals(hex, DbPassWord)){
            return ResponseResult.fail().message("密码错误");
        }

        //看状态 状态为0 不给登录
        Integer state = user.getState();
        if (state == 0){
            return ResponseResult.error().message("账号状态异常,请联系管理员");
        }


        HashMap<String,Object> payload=new HashMap<>();
        payload.put("username",user.getUsername());
        payload.put("nickName",user.getNickName());
        payload.put("uid",user.getId());

        String token =jwtUtil.createToken(payload);


        //token 作为key  ip放在后面
        String ip = IpUtil.getIp(request);
        //由于token太长 摘要算法
        String s = DigestUtil.md5Hex(token);
        String s1= String.valueOf(user.getId());
        stringRedisTemplate.opsForValue().set(s,ip);

        boolean exists = Boolean.TRUE.equals(stringRedisTemplate.hasKey(s1));
        System.out.println("--------------------------"+exists);
        //判断是否存在  存在就删了 重新登录
        if (exists){
            stringRedisTemplate.delete(s1);
            System.out.println("---------------------执行到了这里------");
        }


        String uuid1 = UUID.randomUUID().toString();
        stringRedisTemplate.opsForValue().set(s1,uuid1);


        return ResponseResult.success().data("token",token).data("s1",uuid1).data("nickName",user.getNickName()).message("认证成功");
    }

    @Override
    public ResponseResult userPage(QueryCondition<User> queryCondition) {
//创建分页对象
        Page<User> userPage = new Page<>(queryCondition.getPage(), queryCondition.getLimit());
//获取搜索条件
        User searchParams = queryCondition.getSearchParams();
        String username = searchParams.getUsername();
        Integer deptId = searchParams.getDeptId();
        Integer state=searchParams.getState();

        //根据搜索条件 构造动态sql
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.like(StringUtils.isNotBlank(username),User::getUsername,username)
                .eq(ObjectUtils.isNotNull(deptId),User::getDeptId,deptId)
                .eq(ObjectUtils.isNotNull(state),User::getState,state)
                .orderByDesc(User::getPaiXu)
                .orderByDesc(User::getCreateTime);
        baseMapper.selectPage(userPage, lambda);

        List<User> records = userPage.getRecords();
        long total = userPage.getTotal();


        List<UserVo> userVos=records.stream().map(user ->{
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user,userVo);

            //部门名称
            Integer deptID1=user.getDeptId();
            String deptName = deptMapper.selectById(deptID1).getDeptName();
            userVo.setDeptName(deptName);

            //角色名称
            Integer UId=user.getId();
            LambdaQueryWrapper<UserRole> lambda1 = new QueryWrapper<UserRole>().lambda();
            lambda1.eq(UserRole::getUserId,UId);
            List<Integer> userRoles = userRoleMapper.selectList(lambda1).stream()
                    .map(ur ->ur.getRoleId())
                    .collect(Collectors.toList());

            userVo.setRoleId(userRoles);

            List<String> roles = roleMapper.selectBatchIds(userRoles).stream()
                    .map(role ->role.getRoleCh())
                    .collect(Collectors.toList());
            userVo.setRoleNames(roles);

            return userVo;
        }).collect(Collectors.toList());



        return ResponseResult.success().data("total",total).data("tableData",userVos);
    }

    @Override
    public ResponseResult changeState(HashMap<String, Object> params) {
        Integer state = (Integer) params.get("state");
        Integer id = (Integer) params.get("id");
        if (id==4){
             return ResponseResult.fail().message("超级管理员状态不可修改");
        }
        User user = new User();
        user.setId(id);
        user.setState(state);
        baseMapper.updateById(user);

        return ResponseResult.success().message("状态修改成功");
    }

    @Transactional
    @Override
    public ResponseResult deleteUser(List<Integer> ids) {
      //判定删除的用户是否包含管理员角色
        boolean contains = ids.contains(4);
        if (contains){
            return ResponseResult.fail().message("删除用户包含管理员,不能删除");
        }


        // 删除用户表中的用户信息
        baseMapper.deleteBatchIds(ids);
        // 删除用户和角色关联表中的数据
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.in(UserRole::getUserId,ids);
        userRoleMapper.delete(lambda);

        return ResponseResult.success().message("删除成功");
    }

    @Transactional
    @Override
    public ResponseResult add(UserForm userForm) {
        log.debug("userForm={}",userForm);
        //user
        User user = new User();
        BeanUtils.copyProperties(userForm,user);

        String s = RandomUtil.randomString(8);
        String hex = new Md5Hash("111111", s, 10).toHex();

        user.setSalt(s);
        user.setPassword(hex);
        baseMapper.insert(user);
        Integer userId = user.getId();

        List<Integer> roleId = userForm.getRoleId();
        roleId.forEach(roleId1->{
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId1);
            userRoleMapper.insert(userRole);

        });


        return ResponseResult.success().message("添加成功");
    }



    @Override
    public ResponseResult edit(UserForm userForm) {
        User user = new User();
        BeanUtils.copyProperties(userForm,user);

        //更新用户表

        int i = baseMapper.updateById(user);

        if (i==0){

            return ResponseResult.fail().message("网络异常,请刷新页面后重试");
        }

        Integer id = user.getId();
        //删除用户所有的角色信息
        LambdaQueryWrapper<UserRole> eq = new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, id);
        userRoleMapper.delete(eq);


        List<Integer> roleId = userForm.getRoleId();

        roleId.forEach(roleId1->{
            UserRole userRole = new UserRole();
            userRole.setUserId(id);
            userRole.setRoleId(roleId1);
            userRoleMapper.insert(userRole);
        });

        return ResponseResult.success().message("编辑成功");
    }

    @Override
    public ResponseResult personal(HttpServletRequest request) {
        String token = request.getHeader("authorization");
        Map<String, Object> claims = jwtUtil.getClaims(token);
        Integer id = (Integer) claims.get("uid");

        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getId, id)
                .select(User::getNickName,User::getSex,User::getTel,User::getCity,User::getId,User::getVersion);

        User user = baseMapper.selectOne(lambda);

        return ResponseResult.success().data("personalInfo",user);
    }

    @Override
    public ResponseResult editPersonal(HashMap<String, String> params, HttpServletRequest request) {
        String token = request.getHeader("authorization");
        Map<String, Object> claims = jwtUtil.getClaims(token);
        Integer id = (Integer) claims.get("uid");
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getId, id)
                .select(User::getPassword,User::getSalt,User::getId);

        User user = baseMapper.selectOne(lambda);
        String DbPassword = user.getPassword();
        String Dbsalt = user.getSalt();

        String oldPassword = params.get("oldPassword");
        String newPassword = params.get("newPassword");

        //校验
        String Md5OldPassword = new Md5Hash(oldPassword, Dbsalt, 10).toHex();

        if (!StringUtils.equals(DbPassword, Md5OldPassword)){
            return ResponseResult.fail().message("原始密码不正确");
        }

      String Md5newPassword = new Md5Hash(newPassword, Dbsalt, 10).toHex();

        user.setPassword(Md5newPassword);

        baseMapper.updateById(user);

        String s = DigestUtil.md5Hex(token);
        stringRedisTemplate.delete(s);

        return ResponseResult.success().message("密码修改成功,请重新登录");
    }

    @Override
    public ResponseResult Logout(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        String s = DigestUtil.md5Hex(token);
        stringRedisTemplate.delete(s);
        return ResponseResult.success().message("退出成功");
    }

    @Override
    public ResponseResult getMeuns(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        Integer uid = (Integer) jwtUtil.getClaims(token).get("uid");

        //根据用户id查询用户角色关联表
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId, uid);
        List<Integer> collect = userRoleMapper.selectList(lambda).stream()
                .map(ur -> ur.getRoleId())
                .collect(Collectors.toList());

        //根据角色id 查询角色权限关联表
        LambdaQueryWrapper<RolePers> lambda1 = new QueryWrapper<RolePers>().lambda();
        lambda1.in(RolePers::getRoleId, collect);
        Set<Integer> collect1 = rolePersMapper.selectList(lambda1).stream()
                .map(ur -> ur.getPerId())
                .collect(Collectors.toSet());

        //查询权限表
        List<Permission> collect2 = permissionMapper.selectBatchIds(collect1).stream()
                .filter(permission -> permission.getIsMenu() != 2)
                .collect(Collectors.toList());


        return ResponseResult.success().data("menu", collect2);
    }


}




